From: Cristian-Bogdan Sirb Date: Wed, 5 Apr 2017 14:53:53 +0000 (+0300) Subject: libxc: fix xc_translate_foreign_address() X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~2330 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=ef78bf31077aae1f60b97ac57b36bc66a17b12dd;p=xen.git libxc: fix xc_translate_foreign_address() Currently xc_translate_foreign_address() only checks for the PSE bit on level 2 entries (that's 2 MB pages on x64 and 32-bit with PAE, and 4 MB pages on 32-bit). But the Linux kernel sometimes uses 1 GB pages. This patch fixes that, by checking the PSE bit on level 3 entries if the guest has 4 translation levels (that means 64-bit guests only). Signed-off-by: Cristian-Bogdan Sirb Signed-off-by: Razvan Cojocaru Acked-by: Wei Liu Release-acked-by: Julien Grall --- diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index e2b4cc15fd..01f8dfe513 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1460,6 +1460,9 @@ int xc_lockprof_query(xc_interface *xch, void *xc_memalign(xc_interface *xch, size_t alignment, size_t size); /** + * Avoid using this function, as it does not work for all cases (such + * as 4M superpages, or guests using PSE36). Only used for debugging. + * * Translates a virtual address in the context of a given domain and * vcpu returning the GFN containing the address (that is, an MFN for * PV guests, a PFN for HVM guests). Returns 0 for failure. diff --git a/tools/libxc/xc_pagetab.c b/tools/libxc/xc_pagetab.c index 92eebd6882..db25c20247 100644 --- a/tools/libxc/xc_pagetab.c +++ b/tools/libxc/xc_pagetab.c @@ -93,7 +93,7 @@ unsigned long xc_translate_foreign_address(xc_interface *xch, uint32_t dom, return 0; } paddr = pte & 0x000ffffffffff000ull; - if (level == 2 && (pte & PTE_PSE)) { + if ((level == 2 || (level == 3 && pt_levels == 4)) && (pte & PTE_PSE)) { mask = ((mask ^ ~-mask) >> 1); /* All bits below first set bit */ return ((paddr & ~mask) | (virt & mask)) >> PAGE_SHIFT; }